﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace _1945
{
    public class MovementPattern
    {
        /*
         * har ett antal destination punkter definierade
         * punkter bör vara definierade för att klara olika upplösningar, tex procent av bredd/höjd.
         *  Avstånd kan vara definierade som avstånd från en baspunkt mätt i procent av höjd/bredd
         * 
         * skall eventuellt kunna byta sprite vid punktbyte/punkankomst
         * 
         * kunna räkna ut när man har nått en targetpoint
         * 
         * räkna ut kursen till nästa targetpoint
         * 
         * kunna uppdatera targetpoint, tex att bossen skall röra sig mot spelaren
         */

        public enum DirectionalPattern { 
            
            none            = 0, 
            straightdown    = 1, 
            left            = 2, 
            right           = 3, 
            downright       = 4, 
            downleft        = 5
        
        }

        Vector2[] targetPoints; //vectors to move to/between
        TimeSpan[] waitAtTargetPoints; //how long to wait at each target point
        TimeSpan lastMovement; 
        int currentTargetPoint; //which targetPoint currently at/moving from
        Vector2 direction;  //current heading
        DirectionalPattern directionPattern; //single direction

        //not implemented yet
        //bool loopMovement; // if true reset currentTargetPoint to 0 and loops movement, 
                           // if false then after reaching last targetpoint keep last movementvector


        public MovementPattern(Vector2[] targetPoints, TimeSpan[] waitAtTargetPoints, bool loopMovement)
        {
            this.targetPoints = targetPoints;
            currentTargetPoint = 0;
            this.waitAtTargetPoints = waitAtTargetPoints;
            direction = Vector2.Zero;
            //this.loopMovement = loopMovement;
        }

        public MovementPattern(DirectionalPattern directionPattern)
        {
            this.directionPattern = directionPattern;
            setDirection();
        }



        private void setDirection()
        {
            switch (directionPattern)
            {
                case DirectionalPattern.straightdown:
                    direction = new Vector2(0, 1);
                    break;

                case DirectionalPattern.left:
                    direction = new Vector2(-1, 0);
                    break;

                case DirectionalPattern.right:
                    direction = new Vector2(1, 0);
                    break;

                case DirectionalPattern.downright:
                    direction = new Vector2(1, 1);
                    break;

                case DirectionalPattern.downleft:
                    direction = new Vector2(-1, 1);
                    break;
            }
        }
        
        public Vector2 getDirection(Vector2 position, Vector2 speed, TimeSpan totalElapsedGameTime){

            if (targetPoints != null) //if not using directionPattern
            {

                if (isAtNextTargetPoint(position, speed))
                {
                    //has arrived at next targetpoint                   
                    if (waitedEnoughTime(totalElapsedGameTime))
                    {
                        //has waited enough time at target position
                        currentTargetPoint = getNextTargetPoint();
                        direction = targetPoints[getNextTargetPoint()] - position;
                        direction.Normalize();
                        lastMovement = totalElapsedGameTime;
                    }
                    else
                    {
                        direction.X = 0;
                        direction.Y = 0;
                    }
                    
                }
                else
                {
                    direction = targetPoints[getNextTargetPoint()] - position;
                    direction.Normalize();
                    lastMovement = totalElapsedGameTime;
                }

            }

            return direction;

        }

        private bool isAtNextTargetPoint(Vector2 position, Vector2 speed)
        {
            if (position.X >= targetPoints[getNextTargetPoint()].X - speed.X && position.X <= targetPoints[getNextTargetPoint()].X + speed.X &&
                position.Y >= targetPoints[getNextTargetPoint()].Y - speed.Y && position.Y <= targetPoints[getNextTargetPoint()].Y + speed.Y)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool waitedEnoughTime(TimeSpan totalElapsedGameTime)
        {
            if (totalElapsedGameTime.Subtract(lastMovement).CompareTo(waitAtTargetPoints[currentTargetPoint]) > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private int getNextTargetPoint()
        {
            if (currentTargetPoint == (targetPoints.Count() -1))
            {
                return 0;
            }
            else
            {
                return currentTargetPoint + 1;
            }
        }

    }
}
